﻿using System.Collections.Generic;
using System.ComponentModel.Composition;
using ScrumFactory.Composition.ViewModel;
using ScrumFactory.Composition;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;

namespace ScrumFactory.Windows.ViewModel
{
    

    [Export(typeof(IShellViewModel))]
    public class ShellViewModel : IShellViewModel, INotifyPropertyChanged
    {

        private Project selectedProject;
        private ObservableCollection<object> childWindows = new ObservableCollection<object>();        

        private List<IPanelViewModel> allPanels;

        private IEventAggregator aggregator;
        
        [ImportingConstructor()]
        public ShellViewModel(            
            [Import] IBackgroundExecutor backgroundExecutor,
            [Import] IEventAggregator eventAggregator) {


                AlertMessageViewModel = new MessageBoxViewModel();


                aggregator = eventAggregator;

      
                aggregator.Subscribe<Project>(ScrumFactoryEvent.ProjectCreated, GoToSummaryProjectTabAfterCreation);

                aggregator.Subscribe<IPanelViewModel>(ScrumFactoryEvent.OpenNewWindow, w => { ChildWindows.Add(w.View); });                       
                aggregator.Subscribe<IPanelViewModel>(ScrumFactoryEvent.CloseWindow, w => { ChildWindows.Remove(w.View); });
                        
                aggregator.Subscribe<System.Exception>(ScrumFactoryEvent.ShowAlertMessage, ex => { ShowAlertMessage(ex); });
            
                aggregator.Subscribe<Project>(ScrumFactoryEvent.ViewProjectDetails, ViewProjectDetails);


                MoveWindowCommand = new DelegateCommand(() => { View.DragMove(); });
                CloseWindowCommand = new DelegateCommand(() => { View.Close(); });
                MinimizeWindowCommand = new DelegateCommand(() => { View.WindowState = System.Windows.WindowState.Minimized; });
                MaximizeWindowCommand = new DelegateCommand(() => {
                    if(View.WindowState==System.Windows.WindowState.Maximized)
                        View.WindowState = System.Windows.WindowState.Normal;
                    else
                        View.WindowState = System.Windows.WindowState.Maximized;
                });

                CreateProjectCommand = new DelegateCommand(OpenCreateProjectWindow);
        }


      

        /// <summary>
        /// Gets and sets the selected project.
        /// </summary>
        public Project SelectedProject {
            get {
                return this.selectedProject;
            }
            private set {
                this.selectedProject = value;
                OnPropertyChanged("SelectedProject");
                OnPropertyChanged("WindowTitle");                
                OnPropertyChanged("CurrentSprintLabel");                
            }
        }

        private void ViewProjectDetails(Project p) {

            if (p == null)
                return;
            SelectedProject = p;

           

            
        }


        public IMessageBoxViewModel AlertMessageViewModel { get; set; }

     
        private void OpenCreateProjectWindow() {
            aggregator.Publish(ScrumFactoryEvent.OpenCreateProjectWindow);
        }
        
        private void ShowAlertMessage(System.Exception ex) {

            string exceptionType = ex.GetType().ToString().Replace('.', '_');

            AlertMessageViewModel.Title = Properties.Resources.ResourceManager.GetString(exceptionType + "_errorMessageTitle");
            AlertMessageViewModel.Message = Properties.Resources.ResourceManager.GetString(exceptionType + "_errorMessage");
            string imageSource = Properties.Resources.ResourceManager.GetString(exceptionType + "_errorImageSource");
            if(imageSource!=null)
                AlertMessageViewModel.ImageSource = Properties.Resources.ResourceManager.GetString(exceptionType + "_errorImageSource");

            if (ex is Exceptions.BusinessRuleViolationException) {
                AlertMessageViewModel.Message = ((Exceptions.BusinessRuleViolationException)ex).LocalizedMessage;
                AlertMessageViewModel.Title = ((Exceptions.BusinessRuleViolationException)ex).LocalizedMessageTitle;
            }
                        
            AlertMessageViewModel.Show();
                        
        }

        
        private void GoToSummaryProjectTabAfterCreation(Project project) {            
            ShowProjectTab("PROJECT_SUMMARY_TAB");
        }

        private IPanelViewModel selectedProjectTab;
        public IPanelViewModel SelectedProjectTab {
            get {
                return selectedProjectTab;
            }
            set {
                selectedProjectTab = value;
                OnPropertyChanged("SelectedProjectTab");
            }
        }



        private void ShowProjectTab(string panelUId) {
            if (SelectedProject == null)
                return;
            IPanelViewModel panel = ProjectPanels.SingleOrDefault(p => p.PanelUId.Equals(panelUId, System.StringComparison.OrdinalIgnoreCase));
            if(panel!=null)
                SelectedProjectTab = panel;
        }

        public string CurrentSprintLabel {
            get {
                if (SelectedProject == null)
                    return null;

                if (SelectedProject.Sprints == null || SelectedProject.Sprints.Count==0)
                    return null;
                
                if (SelectedProject.Status == (short)ProjectStatus.PROJECT_DONE)
                    return Properties.Resources.Project_finished;

                if (SelectedProject.Sprints.Last().EndDate < System.DateTime.Today)
                    return Properties.Resources.Project_expired;

                if (SelectedProject.Status == (short)ProjectStatus.PROJECT_STARTED || SelectedProject.Status==(short)ProjectStatus.PROJECT_SUPPORT)
                    return string.Format(Properties.Resources.Sprint_N_of_M, SelectedProject.CurrentSprint.SprintNumber, SelectedProject.Sprints.Count);

                return Properties.Resources.Project_not_started;
            }
        }
      
        /// <summary>
        /// Gets and sets the child windows of the panel.
        /// </summary>
        public ObservableCollection<object> ChildWindows {
            get {
                return this.childWindows;
            }
            private set {
                this.childWindows = value;
                OnPropertyChanged("ChildWindows");                
            }
        }

        [Import(typeof(IShellView))]
        public IShellView View
        {
            get;
            set;
        }

        object IWindowViewModel.View {
            get {
                return this.View;
            }
            set {
                this.View = (IShellView)value;
            }
        }


        public string WindowTitle {
            get {
                if (SelectedProject == null)
                    return "The Scrum Factory";
                return SelectedProject.ProjectName + " [" + SelectedProject.ProjectNumber + "]";
            }
        }

        
        [ImportMany(typeof(IPanelViewModel))]
        protected IEnumerable<IPanelViewModel> AllPanels {
            get {
                return this.allPanels;
            }
            set {
                allPanels = new List<IPanelViewModel>(value.OrderBy(p => p.PanelDisplayOrder));                
                OnPropertyChanged("AllPanels");
                OnPropertyChanged("ProjectPanels");                
                OnPropertyChanged("DockLeftPanels");
                OnPropertyChanged("DockBottomPanels");
            }            
        }
        
        public IEnumerable<IPanelViewModel> ProjectPanels {
            get {
                return AllPanels.Where(p => p.PanelPlacement == PanelPlacements.ProjectTab).ToArray();
            }            
        }
               
        public IEnumerable<IPanelViewModel> DockLeftPanels {
            get {                
                return AllPanels.Where(p => p.PanelPlacement == PanelPlacements.DockPanelLeft).ToArray();
            }            
        }

        public IEnumerable<IPanelViewModel> DockBottomPanels {
            get {
                return AllPanels.Where(p => p.PanelPlacement == PanelPlacements.DockPanelBottom).ToArray();
            }
        }        

        public void Show()
        {
            this.View.Show();
        }


        public ICommand MoveWindowCommand { get; private set; }

        public ICommand CloseWindowCommand { get; private set; }

        public ICommand MinimizeWindowCommand { get; private set; }

        public ICommand MaximizeWindowCommand { get; private set; }

        public ICommand CreateProjectCommand { get; private set; }


        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName) {
            if (PropertyChanged != null) 
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        
    }
}
